package com.nlp.visualization.service.weibo;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.nlp.visualization.common.CONSTANTS;
import com.nlp.visualization.core.seg.ISegmentService;
import com.nlp.visualization.core.seg.SegmentFactory;
import com.nlp.visualization.core.seg.SegmentType;
import com.nlp.visualization.core.seg.filter.SegFilter;
import com.nlp.visualization.pojo.NLP.weibo.WeiboCSVEntity;
import com.nlp.visualization.pojo.NLP.weibo.WeiboContentEntity;
import com.nlp.visualization.service.tasks.WeiboAnalyze2SQLTask;
import com.nlp.visualization.utils.MyFIleUtil;
import com.nlp.visualization.utils.WeiboUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

public class WeiboAnalyzeImpl implements IWeiboAnalyze {

    Logger logger = LoggerFactory.getLogger(WeiboAnalyzeImpl.class);


    /**
     * 将json格式的微博，转为sql格式保存到数据库方便查询
     *
     * @param inputJson
     * @param outputTxt
     */
    public void saveWeibo2SQL(File inputJson, File outputTxt) {

        ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
        try {
            List<WeiboCSVEntity> lines = JSONObject.parseArray(FileUtils.readFileToString(inputJson), WeiboCSVEntity.class);
            // 创建线程池
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            // 提交替换的任务
            forkJoinPool.submit(new WeiboAnalyze2SQLTask(0, lines.size(), lines, queue));
            forkJoinPool.shutdown();
            forkJoinPool.awaitTermination(CONSTANTS.TASK_TIMEOUT, TimeUnit.SECONDS);//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
            MyFIleUtil.writeQueue2File(queue, outputTxt);
        } catch (Exception e) {
            logger.error("微博数据转json时出错");
            e.printStackTrace();

        }
    }

    /**
     * 将json格式的微博，按照作者，指定周期来分别拼接存储
     *
     * @param inJson
     * @param outDir
     * @param cycle
     * @param per
     */
    @Override
    public void joinWeibo2Txt(File inJson, File outDir, char cycle, int per) {

        Gson gson = new Gson();
        Map<String, List<WeiboContentEntity>> userMap = new HashedMap();
        Map<String, List<String>> cycleMap = new HashedMap();
        List<WeiboCSVEntity> lines = MyFIleUtil.parseBigJson(inJson);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SegFilter.FilterBuilder builder = new SegFilter.FilterBuilder();
        builder.enablePunctuation(true)
                .enableStopwords(true);
        SegFilter filter = builder.build();

        //按用户将微博分类
        for (WeiboCSVEntity weibo : lines) {
            WeiboContentEntity weiboContent = gson.fromJson(weibo.getWeibo_info().replaceAll("\\\\", ""), WeiboContentEntity.class);
            if (weiboContent.isIs_reprint_weibo())
                continue;
            List tmp = userMap.get(weibo.getUser_id());
            if (tmp == null) {
                List<WeiboContentEntity> list = new ArrayList<>();
                list.add(weiboContent);
                userMap.put(weibo.getUser_id(), list);
            } else {
                tmp.add(weiboContent);
            }
        }

        //按时间拼接字符串
        Iterator iterator = userMap.entrySet().iterator();
        while (iterator.hasNext()) {

            Map.Entry entry = (Map.Entry) iterator.next();
            String userId = (String) entry.getKey();
            if (userId.equals("1721028404"))
                logger.error("");
            List<WeiboContentEntity> tmp = (List) entry.getValue();
            LinkedList<String> perCycleList = new LinkedList<>();
            Date orgDate = null;
            String buf = "";
            try {
                orgDate = sdf.parse("1999-01-01 00:00:00");
            } catch (ParseException e) {
                logger.error("字符串转日期异常");
                e.printStackTrace();
            }
            Collections.sort(tmp, new Comparator<WeiboContentEntity>() {
                @Override
                public int compare(WeiboContentEntity o1, WeiboContentEntity o2) {
                    return WeiboUtils.getTimeFromStr(o1.getPublish_time()).compareTo(WeiboUtils.getTimeFromStr(o2.getPublish_time()));
                }
            });
            for (WeiboContentEntity content : tmp) {
                Date date;
                String publishTime = WeiboUtils.getTimeFromStr(content.getPublish_time());
                String weibocontent = content.getWeibo_content().split("\u200B\u200B\u200B")[0];
                weibocontent = WeiboUtils.filterEmoji(weibocontent);
                try {
                    date = sdf.parse(publishTime);
                    //如果微博发布当天时间晚于时间界限的话，就
                    if (date.after(orgDate)) {
                        orgDate = addDate(date, cycle, per);
                        perCycleList.add(buf);
                        buf = "";
//                        buf += weibocontent;
                        buf += fillSeg(weibocontent, SegmentType.HANLP_NLP, filter);
                    } else
//                        buf += weibocontent;
                        buf += fillSeg(weibocontent, SegmentType.HANLP_NLP, filter);
                } catch (ParseException e) {
                    logger.error("字符串转日期异常");
                    e.printStackTrace();
                }

            }
            perCycleList.add(buf);
            cycleMap.put(userId, perCycleList);
            int size = perCycleList.size();
            perCycleList.remove(0);
            //用于分别保存的代码
            perCycleList.addFirst((size - 1) + "");
            File out = new File(outDir.getPath() + "/" + per + cycle + "/" + userId + ".txt");
            try {
                WeiboUtils.saveJoinWeiboByPerson(out, perCycleList);
            } catch (IOException e) {
                logger.info("io异常");
                e.printStackTrace();
            }
        }

        //用于保存所有用户的相同周期内微博拼接结果的代码
//        Iterator eachPerson = cycleMap.entrySet().iterator();
//        File out = new File(outDir.getPath() + "/" + per + cycle + "/" + "alluser" + ".txt");
//        while (eachPerson.hasNext()) {
//            Map.Entry entry = (Map.Entry) eachPerson.next();
//            List<String> list = (List) entry.getValue();
//            try {
//                WeiboUtils.saveJoinWeiboByPerson(out, list);
//            } catch (IOException e) {
//                logger.info("io异常");
//                e.printStackTrace();
//            }
//        }


    }

    /**
     * 返回下一个时间节点
     *
     * @param cycle
     * @param per
     * @return
     */
    private Date addDate(Date orgDate, char cycle, int per) {
        Calendar cd = Calendar.getInstance();
        switch (cycle) {
            case 'd':
                cd.setTime(orgDate);
                cd.add(Calendar.DATE, per);
                return cd.getTime();
        }
        return null;

    }


    private String fillSeg(String line, SegmentType method, SegFilter filter) {

        ISegmentService segmentService = SegmentFactory.getInstance();
        String reg = "[\\u4e00-\\u9fa5]+";//判断是否都是汉字
        String content = line;
        try {
            List<String> segResults = segmentService.executeSeg(content, method, filter);
            Iterator iterator = segResults.iterator();
            String buf = "";
            while (iterator.hasNext()) {
                String term = (String) iterator.next();
                if (term.trim().equals(""))
                    continue;
                String SQL = "";
                String[] terms = term.split("/");
                try {
                    if (!terms[0].matches(reg))
                        continue;
                    if (terms.length > 1) {
//                        logger.info(String.join(",", terms));

                        if (terms[1].charAt(0) == 'n' || terms[1].charAt(0) == 'a' || terms[1].charAt(0) == 'd' || terms[1].charAt(0) == 'g')
                            ;
                        else
                            continue;
                    }
                } catch (Exception e) {
                    continue;
                }

                String word = "";
                word = terms[0];
                buf += word + " ";
            }
            return buf;

        } catch (Exception e) {
            logger.error("分词异常");
            e.printStackTrace();
        }

        return "";
    }
}
